package com.ipDev.moyvSys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ipDev.moyvSys.constant.StatusConstant;
import com.ipDev.moyvSys.constant.TimeConstant;
import com.ipDev.moyvSys.domain.dto.PageDTO;
import com.ipDev.moyvSys.domain.dto.ProblemDTO;
import com.ipDev.moyvSys.domain.dto.ProblemListDTO;
import com.ipDev.moyvSys.domain.dto.ProblemPageQueryDTO;
import com.ipDev.moyvSys.domain.po.Choice;
import com.ipDev.moyvSys.domain.po.Problem;
import com.ipDev.moyvSys.domain.po.Section;
import com.ipDev.moyvSys.domain.vo.ProblemVO;
import com.ipDev.moyvSys.mapper.ProblemMapper;
import com.ipDev.moyvSys.service.IChoiceService;
import com.ipDev.moyvSys.service.IProblemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ipDev.moyvSys.service.ISectionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 题目表 服务实现类
 * </p>
 *
 * @author fish
 * @since 2024-10-22
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> implements IProblemService {

    private final IChoiceService choiceService;
    private final ISectionService sectionService;

    @Override
    @Transactional
    public void saveOne(ProblemDTO dto) {
        if (BeanUtil.isEmpty(dto)) {
            //TODO  dto为空 抛出异常
        }
        //TODO 检查section_id是否合法 choices description point是否为空
        //如果choices为空 检查type是否为2(简答题)


        Problem problem = Problem.builder()
                .description(dto.getDescription())
                .point(dto.getPoint())
                .answer(dto.getAnswer())
                .sectionId(dto.getSectionId())
                .type(dto.getType())
                .status(dto.getStatus())
                .image(dto.getImage()).build();
        save(problem);

        //将这个问题对应的选项一起添加到数据库中
        List<Choice> choices = dto.getChoices();
        for (Choice choice : choices) {
            choice.setProblemId(problem.getId());
        }
        choiceService.saveBatch(choices);

    }

    @Override
    @Transactional
    public void delProblem(Integer problemId) {
        removeById(problemId);
        Map<String, Object> map = new HashMap<>();
        map.put("problem_id", problemId);
        choiceService.removeByMap(map);
    }

    @Override
    @Transactional
    public void updateProblem(ProblemDTO dto) {
        if (BeanUtil.isEmpty(dto)) {
            //TODO  dto为空 抛出异常
        }
        if (dto.getProblemId() == null) {
            //TODO　没有problemId 没办法更新 抛出异常
        }
        if (!CollUtil.isEmpty(dto.getChoices())) {
            //如果是非空的选择
            List<Choice> choices = dto.getChoices();
            for (Choice choice : choices) {
                choice.setProblemId(dto.getProblemId());
            }
            choiceService.updateBatchById(choices);
        }

        Problem problem = new Problem();
        problem.setId(dto.getProblemId());
        BeanUtils.copyProperties(dto, problem);
        updateById(problem);
    }

    @Override
    public PageDTO<ProblemVO> queryProblemByPage(ProblemPageQueryDTO dto) {

        Page<Problem> page = lambdaQuery().like(Problem::getDescription, dto.getDescription())
                .eq(Problem::getType, dto.getType())
                .between(dto.getBeginTime() != null && dto.getEndTime() != null
                        , dto.getTimeType().equals(TimeConstant.UPDATE_TIME) ? Problem::getUpdateTime : Problem::getCreateTime
                        , dto.getBeginTime(), dto.getEndTime())
                .eq(dto.getStatus() != null, Problem::getStatus, dto.getStatus())
                .eq(Problem::getSectionId, dto.getSectionId())
                .page(dto.toMpPageDefaultSortByCreateTimeDesc());

        List<Problem> records = page.getRecords();
        ArrayList<ProblemVO> list = new ArrayList<>();
        for (Problem record : records) {
            //将查到的po加工成vo(前端展示需要用到的数据)
            ProblemVO vo = new ProblemVO();
            BeanUtil.copyProperties(record, vo);
            vo.setProblemId(record.getId());
            list.add(vo);
        }
        log.info("放入page中的数据:{}", list);
        return PageDTO.of(page, list);

    }

    @Override
    public List<ProblemVO> getProblemList(ProblemListDTO dto) {
        //sectionId具有更高的优先级 两个都非空就用sectionId查询
        List<Problem> list = null;
        if (dto.getSectionId() != null) {
            list = lambdaQuery().eq(Problem::getSectionId, dto.getSectionId())
                    .eq(Problem::getStatus, StatusConstant.ENABLE)
                    .list();
        } else if (dto.getBookId() != null) {
            //TODO 先查这本书对应的sectionId有哪些 再全部查出来
            List<Section> sectionList = sectionService.lambdaQuery().eq(Section::getBookId, dto.getBookId()).list();
            if (sectionList == null) {
                log.error("没有与书本匹配的章节!");
                return Collections.emptyList();
            }
            List<Integer> sectionIdList = sectionList.stream().map(Section::getId).collect(Collectors.toList());

            list = lambdaQuery().in(Problem::getSectionId, sectionIdList)
                    .eq(Problem::getStatus, StatusConstant.ENABLE)
                    .list();
        }
        //到这里为止是将所有符合条件的题目全部选出
        //要对题目进行随机抽取

        if (list != null) {
            Collections.shuffle(list);
        } else {
            log.error("没有任何符合条件的问题!");
            return Collections.emptyList();
        }
        List<Problem> limitedList = list.stream()
                .limit(dto.getAmount())
                .collect(Collectors.toList());

        //将查出的PO加工成VO返回
        List<ProblemVO> voList = new ArrayList<>();
        for (Problem problem : limitedList) {
            //这里的vo需要用到问题对应的选项信息
            ProblemVO vo = new ProblemVO();
            BeanUtil.copyProperties(problem, vo);
            vo.setProblemId(problem.getId());
            List<Choice> choiceList = choiceService.lambdaQuery()
                    .eq(Choice::getProblemId, problem.getId())
                    .list();
            vo.setChoiceList(choiceList);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    @Transactional
    public void delProblemBatch(List<Integer> list) {
        if (CollUtil.isEmpty(list)) {
            log.error("请求参数不能为空!");
            return;
        }
        List<Problem> problemList = lambdaQuery().in(Problem::getId, list).list();
        List<Integer> problemIdList = problemList.stream().map(Problem::getId).collect(Collectors.toList());

        QueryWrapper<Choice> wrapper = new QueryWrapper<>();
        wrapper.in("problem_id", problemIdList);
        choiceService.remove(wrapper);
    }
}
